#!/bin/bash
#

### BEGIN INIT INFO
# Provides:		idempiere
# Required-Start:	postgresql
# Required-Stop:	postgresql
# Default-Start:	2 3 4 5
# Default-Stop:		1
# Short-Description:	iDempiere server
# Description:		Provides iDempiere ERP-CRM Server startup and shutdown script. Requires PostgreSQL server.
# FileTarget:	/etc/init.d/idempiere
# FileOwner:	root.root
# FilePerms:	0755
#
# chkconfig:	2345 97 06
### END INIT INFO

# processname: idempiere
# Red Hat or SuSE config: /etc/sysconfig/idempiere
# Debian or Ubuntu config: /etc/default/idempiere

# Source function library
if [ -f /lib/lsb/init-functions ]
then
	. /lib/lsb/init-functions
elif [ -f /etc/init.d/functions ]
then
	. /etc/init.d/functions
fi

# Set path if path not set (if called from /etc/rc)
case $PATH in
    "") PATH=/bin:/usr/bin:/sbin:/etc
        export PATH ;;
esac

# initialization
# adjust these variables to your environment
IDEMPIERE_USER=idempiere
IDEMPIERE_HOME=/opt/idempiere-server
# in case you manual install java by use zip or your linux distros, or your java provider have difference pattern of path, please update here
JAVA_HOME=$(ls -r /usr/lib/jvm/java-1[7]-openjdk*/bin/javac | head -1)
JAVA_HOME=$(dirname $( dirname "$JAVA_HOME") )
SU=su
export IDEMPIERE_HOME
export TELNET_PORT=12612

if [ "$(id -u)" != "0" ]
then
    echo "You must be root to run the configure script.  Login as root and then run the configure script."
    exit 1
fi

RETVAL=0
IDEMPIERESTATUS=
MAXSECONDS=120 # max wait 2 minutes
SLEEPSECONDS=2
MAXITERATIONS=$((MAXSECONDS / SLEEPSECONDS))

CONFIG_NAME=idempiere
CONFIGURATION="/etc/sysconfig/$CONFIG_NAME"
if [ -f /etc/redhat-release ]
then
    . /etc/init.d/functions

    init_status()
    {
	return 0
    }
    exit_status()
    {
	exit $?
    }
    success_status()
    {
	success
	echo
    }
    failure_status()
    {
	failure $?
	echo
    }

elif [ -f /etc/SuSE-release ]
then
    . /etc/rc.status

    init_status()
    {
	rc_reset
    }
    success_status()
    {
	echo "OK"
	return 0
    }
    failure_status()
    {
	echo "Failed"
	return 1
    }
    exit_status()
    {
	exit $?
    }

else
    if [ -d /etc/default ]
    then
        CONFIGURATION="/etc/default/$CONFIG_NAME"
    fi

    init_status()
    {
        return 0
    }

    success_status()
    {
        echo "OK"
        return 0
    }

    failure_status()
    {
        echo "Failed"
        return 0
    }

    exit_status()
    {
        exit $?
    }
fi

# Source configuration

[ -f "$CONFIGURATION" ] && . "$CONFIGURATION"

init_status

#
# if_fail()
#
# Evaluates return codes.  If 0, prints "OK", if 1, prints "Failed"
# and exits.  If 2, status is "already done" and nothing is printed.
# The rest of the functions in here all honor this convention.
#
if_fail()
{
    RC="$1"
    REASON="$2"
    if [ "$RC" = "0" ]
    then
        return
    elif [ "$RC" = "2" ]
    then
        return
    fi
    failure_status "${REASON}"
    exit 1
}

#
# write_sysconfig()
#
# Writes the system configuration
#
write_sysconfig()
{
    cat >"$CONFIGURATION" <<EOF

#This is a configuration file for automatic starting of the iDempiere
#Server at system startup. It is generated by running
#'/etc/init.d/idempiere configure'.Please use that method to modify this
#file

# RUN_AT_STARTUP:'true' means to load the Server at system boot.
RUN_AT_STARTUP=${RUN_AT_STARTUP:-false}

# Configuration : Check whether configure has been done or not
CONFIGURE_RUN=${CONFIGURE_RUN}

EOF
    if [ $? != 0 ]
    then
	return 1
    fi
    return 0
}

# configure_perform()
# Create idempiereEnv.properties
# RUN silent-setup-alt.sh
# Import database
configure_perform()
{
    cp ${IDEMPIERE_HOME}/idempiereEnvTemplate.properties ${IDEMPIERE_HOME}/idempiereEnv.properties
    sed -i "s:^IDEMPIERE_HOME=.*:IDEMPIERE_HOME=${IDEMPIERE_HOME}:" ${IDEMPIERE_HOME}/idempiereEnv.properties
    sed -i "s:^JAVA_HOME=.*:JAVA_HOME=${JAVA_HOME}:" ${IDEMPIERE_HOME}/idempiereEnv.properties
    sed -i "s:^ADEMPIERE_DB_PASSWORD=.*:ADEMPIERE_DB_PASSWORD=${ADEMPIERE_DB_PASSWORD}:" ${IDEMPIERE_HOME}/idempiereEnv.properties
    sed -i "s:^ADEMPIERE_DB_SYSTEM=.*:ADEMPIERE_DB_SYSTEM=${ADEMPIERE_DB_SYSTEM}:" ${IDEMPIERE_HOME}/idempiereEnv.properties
    sed -i "s:^ADEMPIERE_WEB_PORT=.*:ADEMPIERE_WEB_PORT=${ADEMPIERE_WEB_PORT}:" ${IDEMPIERE_HOME}/idempiereEnv.properties
    sed -i "s:^ADEMPIERE_SSL_PORT=.*:ADEMPIERE_SSL_PORT=${ADEMPIERE_SSL_PORT}:" ${IDEMPIERE_HOME}/idempiereEnv.properties
    sed -i "s:^ADEMPIERE_APPS_SERVER=.*:ADEMPIERE_APPS_SERVER=0.0.0.0:" ${IDEMPIERE_HOME}/idempiereEnv.properties
    sed -i "s:^ADEMPIERE_KEYSTORE=.*:ADEMPIERE_KEYSTORE=${IDEMPIERE_HOME}/keystore/myKeystore:" ${IDEMPIERE_HOME}/idempiereEnv.properties
    chown idempiere:idempiere ${IDEMPIERE_HOME}/idempiereEnv.properties
    chmod 600 ${IDEMPIERE_HOME}/idempiereEnv.properties

    sed -i "s/:8080/:${ADEMPIERE_WEB_PORT}/g" /usr/share/applications/idempiere-homepage.desktop
    sed -i "s/:8443/:${ADEMPIERE_SSL_PORT}/g" /usr/share/applications/idempiere-webclient.desktop

    if [ -f ${IDEMPIERE_HOME}/silent-setup-alt.sh ]
    then
     	echo -n "Deploying iDempiere ERP server..."
       	$SU ${IDEMPIERE_USER} -c "cd ${IDEMPIERE_HOME}; ./silent-setup-alt.sh"
	echo "Done"
    fi
    grep "${ADEMPIERE_WEB_PORT}" ${IDEMPIERE_HOME}/jettyhome/etc/jetty-http.xml > /dev/null 2>&1
    if [ $? -ne 0 ]
    then
        echo "Error deploying iDempiere, please verify and try again"
        exit 1
    fi

    if [ "x${ADEMPIERE_DB_SYSTEM}" = "x^TryLocalConnection^" ]
    then
        # recreate idempiere user from here as the RUN_ImportIdempiere requires it
        $SU postgres -c "cd; dropdb -U postgres idempiere" # > /dev/null 2>&1
        $SU postgres -c "cd; dropuser -U postgres idempiere" # > /dev/null 2>&1
        $SU postgres -c "cd; psql -U postgres -c \"CREATE ROLE adempiere SUPERUSER LOGIN PASSWORD '${ADEMPIERE_DB_PASSWORD}'\"" # > /dev/null 2>&1
    fi

    if [ -f ${IDEMPIERE_HOME}/utils/RUN_ImportIdempiere.sh ]
    then
        echo -n "Importing seed database..."
       	$SU ${IDEMPIERE_USER} -c "cd ${IDEMPIERE_HOME}/utils; ( echo "" | ./RUN_ImportIdempiere.sh )" # > /dev/null 2>&1
	echo "Done"
        echo -n "Applying latest migration scripts ..."
       	$SU ${IDEMPIERE_USER} -c "cd ${IDEMPIERE_HOME}/utils; ./RUN_SyncDB.sh" # > /dev/null 2>&1
	echo "Done"
        echo -n "Signing DB ..."
       	$SU ${IDEMPIERE_USER} -c "cd ${IDEMPIERE_HOME}; ./sign-database-build-alt.sh" # > /dev/null 2>&1
	echo "Done"
    fi
    $SU ${IDEMPIERE_USER} -c "cd; export PGPASSWORD=${ADEMPIERE_DB_PASSWORD}; psql -d idempiere -U adempiere -h localhost -p 5432 -c ''" > /dev/null 2>&1
    if [ $? -ne 0 ]
    then
        echo "Cannot connect to idempiere database, please verify and try again"
        exit 1
    fi
    $SU ${IDEMPIERE_USER} -c "cd; export PGPASSWORD=${ADEMPIERE_DB_PASSWORD}; psql -d idempiere -U adempiere -h localhost -p 5432 -c 'select count(*) from ad_system' 2>&1 | grep '1$'" > /dev/null 2>&1
    if [ $? -ne 0 ]
    then
        echo "Database not imported correctly, please verify and try again"
        exit 1
    fi

    chmod 700 ${IDEMPIERE_HOME}/utils/myEnvironment.*

    echo "Installation Completed Successfully."

    return 0
}

checkportused()
{
port=$(netstat -n --tcp --listen | grep :"$1" | awk '{print $4}' | cut -d':' -f2)
if [ "$port" = "$1" ]
then
    return 0  # Used
else
    return 1  # Not Used
fi
}

#
#configure_ask()
#
# Ask configuration questions,setting the variables.
#
configure_ask()
{
	cat <<EOF

iDempiere ERP Server Configuration
-------------------------------------------------
This will configure on-boot properties of iDempiere ERP Server.
The following questions will determine whether the database should
be starting upon system boot, the ports it will use, and the passwords that
will be used for database accounts.  Press <Enter> to accept the defaults.
Ctrl-C will abort.

EOF
    # TODO: ask for certificate data (or integrate with openssl certificate)
    # TODO: ask for mail server settings
    # TODO: ask for postgres port (and perhaps machine if it's remote)

    #get the http port value
    while :
    do
	while :
	do
            echo -n "Specify the HTTP port that will be used for iDempiere server [8080]:"
            read -r LINE
            if [ -z "$LINE" ]
            then
                LINE=8080
            fi
            if checkportused "$LINE"
            then
                echo "Port $port appears to be in use by another application.
Please specify a different port."
            else
                break;
            fi
        done

	case "$LINE" in
	"")
            break
            ;;
        *[^0-9]*)
            echo "Invalid http port: $LINE"
            ;;
        *)
            ADEMPIERE_WEB_PORT=$LINE
            break
            ;;
	esac
    done

    #get the https port value
    while :
    do
	while :
	do
            echo -n "Specify the HTTPS port that will be used for iDempiere server [8443]:"
            read -r LINE
            if [ -z "$LINE" ]
            then
                LINE=8443
            fi
            if checkportused "$LINE"
            then
                echo "Port $port appears to be in use by another application.
Please specify a different port."
            else
                break;
            fi
        done

	case "$LINE" in
	"")
            break
            ;;
        *[^0-9]*)
            echo "Invalid https port: $LINE"
            ;;
        *)
            ADEMPIERE_SSL_PORT=$LINE
            break
            ;;
	esac
    done

    #get the idempiere database password
    while :
    do
        echo -n "Specify a password to be used for adempiere database account:"
	while :
	do
	    stty -echo > /dev/null 2>&1
	    temp=$(echo "$IFS")
            export IFS="\n"	
	    while :
  	    do
	        read -r LINE
                while [ -z "$LINE" ]
	        do
		    echo
		    echo -n "Password can't be null. Enter password:"
	            read -r LINE
	        done

	        result=$(expr index "$LINE" [\'\"])
	        if [ "$result" != 0 ];
	        then
             	    echo
	            echo -n "The password you entered contains invalid characters. Enter password:"	
	        else
		    break
	        fi
	    done
	    echo
	    echo -n "Confirm the password:"
	    read -r LINE1
	    echo
            if [ "$LINE" != "$LINE1" ];
	    then
		echo
		echo -n "Passwords do not match.  Enter the password:"
	    else
		break
	    fi
	done
        stty echo > /dev/null 2>&1
        ADEMPIERE_DB_PASSWORD=$LINE
	export IFS=$temp
        break;
    done

    #get the postgres database password
    while :
    do
        echo -n "Specify the password of the user postgres on postgres database
(if empty then local connection will be tried):"
	while :
	do
	    stty -echo > /dev/null 2>&1
	    temp=`echo $IFS`
            export IFS="\n"	
	    while :
  	    do
	        read -r LINE
                if [ -z "$LINE" ]
	        then
		    break
	        fi

	        result=$(expr index "$LINE" [\'\"])
	        if [ "$result" != 0 ];
	        then
             	    echo
	            echo -n "The password you entered contains invalid characters. Enter password:"
	        else
		    break
	        fi
	    done
	    echo
            if [ -z "$LINE" ]
            then
                # Empty postgres password verify connection with local postgres user
                $SU postgres -c "cd; psql -U postgres -c ''"
                if [ $? -eq 0 ]
                then
                    break
                fi
                echo -n "Could not connect locally with user postgres.
NOTE: You can verify pg_hba.conf to check if this line is enabled
local   all         postgres                          ident
Enter postgres password:"
            else
                PGPASSWORD=$LINE
                export PGPASSWORD
                psql -U postgres -d template1 -h localhost -p 5432 -c ''
                if [ $? -eq 0 ]
                then
                    break
                fi
                echo -n "Could not connect with user postgres to database template with such password.
NOTE: You can check the file pg_hba.conf to validate that connection is allowed,
      or check that postgresql server allows tcp/ip connections on port 5432
      or check that user postgres database password is correctly set.
Enter postgres password:"
            fi
	done
        stty echo > /dev/null 2>&1
	if [ -z "$LINE" ]
	then
	    LINE="^TryLocalConnection^"
	fi
        ADEMPIERE_DB_SYSTEM=$LINE
	export IFS=$temp
        break;
    done

    while :
    do
	echo
        echo -n "Do you want iDempiere ERP Server to be started on boot (y/n) [y]:"
        read -r LINE
	if [ -z "$LINE" ]
	then
	    RUN_AT_STARTUP=true
	fi
        echo
        case "$LINE" in
        "")
            break
            ;;
        y|Y)
            RUN_AT_STARTUP=true
            break
            ;;
        n|N)
            RUN_AT_STARTUP=false
            break
            ;;
        *)
            echo "Invalid response: $LINE " >&2
            break
        esac
    done
}

getidempierestatus() {
    IDEMPIERESTATUSSTRING=$(ps ax | grep java | grep ${IDEMPIERE_HOME} | grep -v grep)
    echo "$IDEMPIERESTATUSSTRING" | grep -q ${IDEMPIERE_HOME}
    IDEMPIERESTATUS=$?
}

configure()
{
	if [ "${CONFIGURE_RUN}" = "true" ]
	then
		echo "iDempiere is already configured"
	exit 1
	fi
	configure_ask
	configure_perform
	CONFIGURE_RUN=true
	write_sysconfig
	echo "To access the iDempiere Server Home Page, start the server with:"
	echo "SYSTEMCTL_SKIP_REDIRECT=1 /etc/init.d/idempiere start"
	echo "and then go to \"https://127.0.0.1:${ADEMPIERE_SSL_PORT}\""

}

start () {

    if [ "${CONFIGURE_RUN}" != "true" ]		
    then
	echo "iDempiere is not configured.  You must run
'/etc/init.d/idempiere configure' as the root user to configure the server."
	exit 0
    fi

    getidempierestatus
    if [ $IDEMPIERESTATUS -eq 0 ] ; then
        echo "iDempiere is already running"
        return 1
    fi
    echo -n "Starting iDempiere ERP: "
    export LOGFILE=$IDEMPIERE_HOME/log/idempiere_$(date +%Y%m%d%H%M%S).log
    $SU ${IDEMPIERE_USER} -c "mkdir -p $IDEMPIERE_HOME/log"
    $SU ${IDEMPIERE_USER} -c "export TELNET_PORT=$TELNET_PORT;cd $IDEMPIERE_HOME;$IDEMPIERE_HOME/idempiere-server.sh &> $LOGFILE &"
    RETVAL=$?
    if [ $RETVAL -eq 0 ] ; then
        # wait for server to be confirmed as started in logfile
        STATUSTEST=0
        ITERATIONS=0
        while [ $STATUSTEST -eq 0 ] ; do
            sleep $SLEEPSECONDS
            grep -q '.*LoggedSessionListener.contextInitialized: iDempiere context initialized.*' < "$LOGFILE" && STATUSTEST=1
            echo -n "."
            ITERATIONS=$((ITERATIONS + 1))
            if [ $ITERATIONS -gt $MAXITERATIONS ]
                then
                break
            fi
        done
        if [ $STATUSTEST -eq 0 ]
        then
            log_warning_msg "Service hasn't started within the timeout allowed, please review file $LOGFILE to see the status of the service"
        else
            log_success_msg "Service started"
        fi
        echo
    else
        log_failure_msg "Service not started"
    echo
    fi
    RETVAL=$?
    return $RETVAL
}

stop () {

    if [ "${CONFIGURE_RUN}" != "true" ]		
    then
	echo "iDempiere is not configured.  You must run
'/etc/init.d/idempiere configure' as the root user to configure the server."
	exit 0
    fi

    getidempierestatus
    if [ $IDEMPIERESTATUS -ne 0 ] ; then
	  echo "iDempiere is already stopped"
	  return 1
    fi
    echo -n "Stopping iDempiere ERP: "
    cd $IDEMPIERE_HOME/utils || exit
    # try shutdown from OSGi console, then direct kill with signal 15, then signal 9
    log_warning_msg "Trying shutdown from OSGi console"
    ( echo exit; echo y; sleep 5 ) | telnet localhost ${TELNET_PORT} > /dev/null 2>&1
    getidempierestatus
    if [ $IDEMPIERESTATUS -ne 0 ] ; then
        log_success_msg "Service stopped with OSGi shutdown"
    else
        log_warning_msg "Trying direct kill with signal -15"
        kill -15 -$(ps ax o pgid,command | grep ${IDEMPIERE_HOME} | grep -v grep | sed -e 's/^ *//g' | cut -f 1 -d " " | sort -u)
        sleep 5
        getidempierestatus
        if [ $IDEMPIERESTATUS -ne 0 ] ; then
            log_success_msg "Service stopped with kill -15"
        else
            log_warning_msg "Trying direct kill with signal -9"
            kill -9 -$(ps ax o pgid,command | grep ${IDEMPIERE_HOME} | grep -v grep | sed -e 's/^ *//g' | cut -f 1 -d " " | sort -u)
            sleep 5
            getidempierestatus
            if [ $IDEMPIERESTATUS -ne 0 ] ; then
                log_success_msg "Service stopped with kill -9"
            else
                log_warning_msg "Service hasn't stopped"
            fi
        fi
    fi
    return $RETVAL
}

restart () {
    stop
    sleep $SLEEPSECONDS
    start
}

condrestart () {
    getidempierestatus
    if [ $IDEMPIERESTATUS -eq 0 ] ; then
	restart
    fi
}

dostatus () {
    getidempierestatus
    if [ $IDEMPIERESTATUS -eq 0 ] ; then
	echo
	echo "iDempiere is running:"
	ps ax | grep ${IDEMPIERE_HOME} | grep -v grep | sed 's/^[[:space:]]*\([[:digit:]]*\).*:[[:digit:]][[:digit:]][[:space:]]\(.*\)/\1 \2/'
	echo
    else
	echo "iDempiere is stopped"
    fi
}

case "$1" in
    start)
	if test -f "$CONFIGURATION"
	then
            if test "${RUN_AT_STARTUP}" != "true"
            then
		exit 0
	    fi
	else
	    echo "iDempiere is not configured.  You must run
'/etc/init.d/idempiere configure' as the root user to configure the server."
	    exit 0
	fi
	start
	;;
    configure)
        configure
        ;;
    stop)
	stop
	;;
    restart|reload|force-reload)
	restart
	;;
    condrestart)
	condrestart
	;;
    status)
	dostatus
	;;
    enable)
	if test -f "$CONFIGURATION"
	then
            RUN_AT_STARTUP=true
	    write_sysconfig
	else
	    echo "iDempiere is not configured.  You must run
'/etc/init.d/idempiere configure' as the root user to configure the server."
	    exit 0
	fi
        ;;
  disable)
	if test -f "$CONFIGURATION"
	then
            RUN_AT_STARTUP=false
	    write_sysconfig
	else
	    echo "iDempiere is not configured.  You must run
'/etc/init.d/idempiere configure' as the root user to configure the server."
	    exit 0
	fi
	;;
    *)
        echo $"Usage: $0 {start|stop|restart|force-reload|configure|status|enable|disable}"
        exit 1

esac

exit 0
